/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved.
 * Description: 异构集合通信NPU侧notify
 */
#include "bare_notify.h"

namespace hccl {

BareNotify::BareNotify(NotifyType notifyType) : NotifyBase(notifyType)
{
}

BareNotify::BareNotify(NotifyType notifyType, HcclNotifyInfo notifyInfo)
    : NotifyBase(notifyType, notifyInfo)
{
}

BareNotify::~BareNotify()
{
    (void)Close();
    (void)Destroy();
}

HcclResult BareNotify::Open()
{
    HcclResult ret = hrtHalDrvOpenIpcNotify(reinterpret_cast<char *>(notifyInfo_.ipcNotify.ipcName), &drvinfo);
    if (ret != HCCL_SUCCESS) {
        HCCL_ERROR("[BareNotify][Open] hrtHalDrvOpenIpcNotify fail");
        return ret;
    }
    isOpen = true;
    HCCL_INFO("Open notify:[%s].", notifyInfo_.ipcNotify.ipcName);
    return HCCL_SUCCESS;
}

HcclResult BareNotify::Close()
{
    if (isOpen) {
        HcclResult ret = hrtHalDrvCloseIpcNotify(reinterpret_cast<char *>(notifyInfo_.ipcNotify.ipcName),
            &drvinfo);
        isOpen = false;
        if (ret != HCCL_SUCCESS) {
            HCCL_ERROR("[BareNotify][Close]hrtHalDrvCloseIpcNotify fail");
            return ret;
        }
    }

    return HCCL_SUCCESS;
}

HcclResult BareNotify::Wait(Stream& stream, HcclDispatcher dispatcher, s32 stage, u32 timeOut)
{
    HcclResult ret = hrtNotifyWaitWithTimeOut(notifyPtr, stream.ptr(), timeOut);
    if (ret != HCCL_SUCCESS) {
        HCCL_ERROR("[BareNotify][hrtNotifyWaitWithTimeOut] hrtNotifyWaitWithTimeOut fail");
        return HCCL_E_RUNTIME;
    }
    return HCCL_SUCCESS;
}

HcclResult BareNotify::Post(Stream& stream, HcclDispatcher dispatcher, s32 stage)
{
    CHK_RET(hrtHalDrvIpcNotifyRecord(reinterpret_cast<char *>(notifyInfo_.ipcNotify.ipcName)));
    return HCCL_SUCCESS;
}

HcclResult BareNotify::Wait(Stream& stream, HcclDispatcher dispatcher, s32 stage, u32 timeOut,
    u32 userRank, u32 remoteUserRank)
{
    return Wait(stream, dispatcher, stage, timeOut);
}

HcclResult BareNotify::Post(Stream& stream, HcclDispatcher dispatcher, s32 stage, u32 remoteUserRank)
{
    return Post(stream, dispatcher, stage);
}

HcclResult BareNotify::SetIpc()
{
    SecIpcName_t ipcName;
    HcclResult ret = hrtIpcSetNotifyName(notifyPtr, reinterpret_cast<u8 *>(ipcName.ipcName),
        sizeof(ipcName.ipcName));
    CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[SetIpc][hrtIpcSetNotifyName]errNo[0x%016llx]  "\
        " IPC set notify name fail. return[%d] name len=[%zu].", HCCL_ERROR_CODE(HCCL_E_RUNTIME),\
        ret, sizeof(ipcName.ipcName)), HCCL_E_RUNTIME);
    if (memcpy_s(notifyInfo_.ipcNotify.ipcName, HCCL_IPC_MEM_NAME_LEN,
        reinterpret_cast<char *>(ipcName.ipcName), sizeof(ipcName.ipcName)) != EOK) {
        HCCL_ERROR("ipcName:%s, size:%u", ipcName.ipcName, sizeof(ipcName.ipcName));
        return HCCL_E_MEMORY;
    }
    HCCL_DEBUG("[BareNotify][SetIpc]ipcName:%s, size:%u.", ipcName.ipcName, sizeof(ipcName.ipcName));

    return HCCL_SUCCESS;
}

HcclResult BareNotify::Grant(s64 recvId)
{
    // 设置notify 的白名单
    HCCL_DEBUG("[BareNotify][Grant]pid[%d], withIpc[%d]",
        recvId, notifyInfo_.ipcNotify.withIpc);
    CHK_RET(hrtSetIpcNotifyPid(notifyInfo_.ipcNotify.ipcName, reinterpret_cast<s32*>(&recvId),
        IPC_NOTIFY_PID_ARRAY_SIZE));

    return HCCL_SUCCESS;
}

HcclResult BareNotify::Alloc()
{
    HcclResult ret = HCCL_SUCCESS;
    s32 devId = 0;
    ret = hrtGetDevice(&devId);
    if (ret != HCCL_SUCCESS) {
        HCCL_ERROR("[BareNotify][Alloc]get deviceId %d failed", devId);
        return ret;
    }
    HCCL_INFO("[BareNotify][Alloc]get deviceId %d ", devId);
    ret = hrtNotifyCreate(devId, &notifyPtr);
    if (ret != HCCL_SUCCESS) {
        HCCL_ERROR("[BareNotify][alloc]devId[%d] rtNotifyCreate fail", devId);
        return ret;
    }
    CHK_PRT_RET(notifyPtr == nullptr, HCCL_ERROR("[BareNotify][Alloc]errNo[0x%016llx] Notify create failed. "\
        "notify is nullptr", HCCL_ERROR_CODE(HCCL_E_RUNTIME)), HCCL_E_RUNTIME);
    HCCL_INFO("[BareNotify][Alloc]BareNotify alloc success. type_:%u, ptr:%p", notifyInfo_.type, notifyPtr);

    return HCCL_SUCCESS;
}

HcclResult BareNotify::Destroy()
{
    if (notifyPtr != nullptr) {
        CHK_RET(hrtNotifyDestroy(notifyPtr));
        HCCL_INFO("[BareNotify][Free] ptr[%p] free succ", notifyPtr);
        notifyPtr = nullptr;
    }
    return HCCL_SUCCESS;
}

void BareNotify::Break()
{
    return;
}
}